//
//  UIView+GradientColor.m
//  Pods
//
//  Created by Apple on 2022/11/4.
//

#import "UIView+GradientColor.h"
#import <objc/runtime.h>

typedef struct {
    CGPoint startPoint;
    CGPoint endPoint;
} YCGradientColorPoints;

static inline YCGradientColorPoints FCPointsMake(CGFloat x0, CGFloat y0, CGFloat x1, CGFloat y1) {
    YCGradientColorPoints points;
    points.startPoint = CGPointMake(x0, y0);
    points.endPoint = CGPointMake(x1, y1);
    return points;
}

@interface UIView (Private)

@property (nonatomic, strong) NSArray<UIColor *> *enabledGradientColors;           //可用背景色（渐变）
@property (nonatomic, strong) NSArray<UIColor *> *disabledGradientColors;          //不可用背景色（渐变）

@end


@implementation UIView (GradientColor)

+ (Class)layerClass {
    return [CAGradientLayer class];
}

- (BOOL)isGradientColorLayer {
    return [self.layer isKindOfClass:[CAGradientLayer class]];
}

- (NSArray *)yc_CGColorsFromUIColors:(NSArray<UIColor *> *)colors {
    if (colors.count == 0) {
        return nil;
    }
    NSMutableArray *theColors = [@[] mutableCopy];
    
    for (UIColor *color in colors) {
        if ([color isKindOfClass:[UIColor class]]) {
            [theColors addObject:((__bridge id)color.CGColor)];
        } else {
            [theColors addObject:color];
        }
    }
    return theColors;
}

- (YCGradientColorPoints)yc_pointsForDirection:(YCGradientColorDirection)direction {
    
    YCGradientColorPoints myPoints = FCPointsMake(0, 0, 1, 0);
    
    switch (direction) {
        case YCGradientColorDirectionHorizonal: {
            myPoints = FCPointsMake(0, 0, 1, 0);
        }
            break;
        case YCGradientColorDirectionVertical: {
            myPoints = FCPointsMake(0, 1, 0, 0);
        }
            break;
        case YCGradientColorDirectionTopLeftToBottomRight: {
            myPoints = FCPointsMake(0, 0, 1, 1);
        }
            break;
        case YCGradientColorDirectionTopRightToBottomLeft: {
            myPoints = FCPointsMake(1, 0, 0, 1);
        }
            break;
        default:
            break;
    }
    return myPoints;
}

- (void)addGradientColorWithColors:(NSArray<UIColor *> *)colors direction:(YCGradientColorDirection)direction {
    if ([self isGradientColorLayer]) {
        //渐变颜色
        ((CAGradientLayer *)self.layer).colors = [self yc_CGColorsFromUIColors:colors];
        
        //渐变方向
        YCGradientColorPoints points = [self yc_pointsForDirection:direction];
        ((CAGradientLayer *)self.layer).startPoint  = points.startPoint;
        ((CAGradientLayer *)self.layer).endPoint    = points.endPoint;
    }
}

- (void)addGradientColorWithColors:(NSArray<UIColor *> *)colors startPoint:(CGPoint)startPoint endPoint:(CGPoint)endPoint {
    if ([self isGradientColorLayer]) {
        //渐变颜色
        ((CAGradientLayer *)self.layer).colors = [self yc_CGColorsFromUIColors:colors];
        //渐变方向
        ((CAGradientLayer *)self.layer).startPoint  = startPoint;
        ((CAGradientLayer *)self.layer).endPoint    = endPoint;
    }
}

//设置渐变色
- (void)addGradientColors:(NSArray<UIColor *> *)colors {
    if (![self isGradientColorLayer]) return;
    
    if (self.gradientColorLocations) {
        ((CAGradientLayer *)self.layer).locations = self.gradientColorLocations;
    }
    
    ((CAGradientLayer *)self.layer).colors = [self yc_CGColorsFromUIColors:colors];
    ((CAGradientLayer *)self.layer).startPoint  = self.gradientColorStartPoint;
    ((CAGradientLayer *)self.layer).endPoint    = self.gradientColorEndPoint;
}


- (BOOL)gradientEnabled {
    return [objc_getAssociatedObject(self, _cmd) boolValue];
}

- (void)setGradientEnabled:(BOOL)gradientEnabled {
    objc_setAssociatedObject(self, @selector(gradientEnabled), @(gradientEnabled), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    
    if (gradientEnabled) {
        if (self.enabledGradientColors) {
            [self addGradientColors:self.enabledGradientColors];
        }
    } else {
        if (self.disabledGradientColors) {
            [self addGradientColors:self.disabledGradientColors];
        }
    }
}

- (void)setGradientColors:(NSArray<UIColor *> *)colors forState:(YCGradientColorState)state {
    if (state & YCGradientColorStateNormal) {
        self.enabledGradientColors = colors;
        if (!self.gradientEnabled) {
            self.gradientEnabled = YES;
        }
    } else if (state & YCGradientColorStateDisabled) {
        self.disabledGradientColors = colors;
    }
}

- (YCGradientColorDirection)gradientColorDirection {
    return (YCGradientColorDirection)[objc_getAssociatedObject(self, _cmd) integerValue];
}

- (void)setGradientColorDirection:(YCGradientColorDirection)gradientColorDirection {
    objc_setAssociatedObject(self, @selector(gradientColorDirection), @(gradientColorDirection), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    
    YCGradientColorPoints points = [self yc_pointsForDirection:gradientColorDirection];
    self.gradientColorStartPoint = points.startPoint;
    self.gradientColorEndPoint   = points.endPoint;
}

- (void)setEnabledGradientColors:(NSArray<UIColor *> *)enabledGradientColors {
    objc_setAssociatedObject(self, @selector(enabledGradientColors), enabledGradientColors, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (NSArray<UIColor *> *)enabledGradientColors {
    return objc_getAssociatedObject(self, _cmd);
}


- (void)setDisabledGradientColors:(NSArray<UIColor *> *)disabledGradientColors {
    objc_setAssociatedObject(self, @selector(disabledGradientColors), disabledGradientColors, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (NSArray<UIColor *> *)disabledGradientColors {
    return objc_getAssociatedObject(self, _cmd);
}


- (void)setGradientColorLocations:(NSArray<NSNumber *> *)gradientColorLocations {
    objc_setAssociatedObject(self, @selector(gradientColorLocations), gradientColorLocations, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (NSArray<NSNumber *> *)gradientColorLocations {
    return objc_getAssociatedObject(self, _cmd);
}

- (void)setGradientColorStartPoint:(CGPoint)gradientColorStartPoint {
    objc_setAssociatedObject(self, @selector(gradientColorStartPoint), [NSValue valueWithCGPoint:gradientColorStartPoint], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    
    self.gradientEnabled = self.gradientEnabled;
}

- (CGPoint)gradientColorStartPoint {
    return [objc_getAssociatedObject(self, _cmd) CGPointValue];
}

- (void)setGradientColorEndPoint:(CGPoint)gradientColorEndPoint {
    objc_setAssociatedObject(self, @selector(gradientColorEndPoint), [NSValue valueWithCGPoint:gradientColorEndPoint], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    
    self.gradientEnabled = self.gradientEnabled;
}

- (CGPoint)gradientColorEndPoint {
    return [objc_getAssociatedObject(self, _cmd) CGPointValue];
}

@end





@implementation UIImageView (GradientColor)

//此处最好不要改，或者返回 [CALayer class]，否则 UIImageView 会崩溃
+ (Class)layerClass {
    return [CALayer class];
}

@end


@implementation UIButton (GradientColor)

+ (Class)layerClass {
    return [CAGradientLayer class];
}

@end
